use super::trend_indicators::CpuFeatures;
use super::simd_advanced::SimdResult;
use std::marker::PhantomData;

/// 向量化策略枚举
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum VectorizeStrategy {
    /// 自动选择最佳策略
    Auto,
    /// 使用AVX-512指令集
    Avx512,
    /// 使用AVX2指令集
    Avx2,
    /// 使用SSE4.2指令集
    Sse4,
    /// 使用标量代码（无向量化）
    Scalar,
}

/// 并行策略枚举
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ParallelStrategy {
    /// 自动选择最佳策略
    Auto,
    /// 使用线程池并行处理
    ThreadPool,
    /// 使用任务分割并行处理
    TaskSplit,
    /// 使用单线程处理
    SingleThread,
}

/// 计算配置
#[derive(Debug, Clone)]
pub struct ComputeConfig {
    /// 向量化策略
    pub vectorize: VectorizeStrategy,
    /// 并行策略
    pub parallel: ParallelStrategy,
    /// 块大小
    pub chunk_size: usize,
    /// 线程数
    pub num_threads: usize,
}

impl Default for ComputeConfig {
    fn default() -> Self {
        Self {
            vectorize: VectorizeStrategy::Auto,
            parallel: ParallelStrategy::Auto,
            chunk_size: 1024,
            num_threads: num_cpus::get(),
        }
    }
}

impl ComputeConfig {
    /// 创建新的计算配置
    pub fn new() -> Self {
        Self::default()
    }
    
    /// 设置向量化策略
    pub fn with_vectorize(mut self, strategy: VectorizeStrategy) -> Self {
        self.vectorize = strategy;
        self
    }
    
    /// 设置并行策略
    pub fn with_parallel(mut self, strategy: ParallelStrategy) -> Self {
        self.parallel = strategy;
        self
    }
    
    /// 设置块大小
    pub fn with_chunk_size(mut self, size: usize) -> Self {
        self.chunk_size = size;
        self
    }
    
    /// 设置线程数
    pub fn with_threads(mut self, threads: usize) -> Self {
        self.num_threads = threads;
        self
    }
    
    /// 根据CPU特性自动配置
    pub fn auto_configure(&mut self) {
        let features = CpuFeatures::detect();
        
        // 配置向量化策略
        self.vectorize = if features.has_avx512f {
            VectorizeStrategy::Avx512
        } else if features.has_avx2 {
            VectorizeStrategy::Avx2
        } else if features.has_sse4_2 {
            VectorizeStrategy::Sse4
        } else {
            VectorizeStrategy::Scalar
        };
        
        // 配置并行策略
        let num_cores = num_cpus::get();
        self.parallel = if num_cores >= 4 {
            ParallelStrategy::ThreadPool
        } else if num_cores >= 2 {
            ParallelStrategy::TaskSplit
        } else {
            ParallelStrategy::SingleThread
        };
        
        // 配置块大小
        self.chunk_size = match self.vectorize {
            VectorizeStrategy::Avx512 => 2048,
            VectorizeStrategy::Avx2 => 1024,
            VectorizeStrategy::Sse4 => 512,
            _ => 256,
        };
        
        // 配置线程数
        self.num_threads = num_cores;
    }
}

/// 向量化处理器
pub struct VectorizedProcessor<T, R> {
    config: ComputeConfig,
    _marker: PhantomData<(T, R)>,
}

impl<T, R> VectorizedProcessor<T, R> {
    /// 创建新的向量化处理器
    pub fn new(config: ComputeConfig) -> Self {
        Self {
            config,
            _marker: PhantomData,
        }
    }
    
    /// 获取当前配置
    pub fn config(&self) -> &ComputeConfig {
        &self.config
    }
    
    /// 更新配置
    pub fn update_config(&mut self, config: ComputeConfig) {
        self.config = config;
    }
}

/// 滑动窗口处理器
pub struct WindowProcessor {
    window_size: usize,
    config: ComputeConfig,
}

impl WindowProcessor {
    /// 创建新的滑动窗口处理器
    pub fn new(window_size: usize, config: ComputeConfig) -> Self {
        Self {
            window_size,
            config,
        }
    }
    
    /// 处理数据
    pub fn process<F>(&self, data: &[f64], mut processor: F) -> SimdResult<Vec<f64>>
    where
        F: FnMut(&[f64]) -> SimdResult<f64>,
    {
        let len = data.len();
        let mut result = Vec::with_capacity(len);
        
        // 填充前面的NaN值
        for _ in 0..self.window_size.saturating_sub(1) {
            result.push(f64::NAN);
        }
        
        // 处理每个窗口
        for i in self.window_size.saturating_sub(1)..len {
            let start = i + 1 - self.window_size;
            let window = &data[start..=i];
            let value = processor(window)?;
            result.push(value);
        }
        
        Ok(result)
    }
}